// /**
// *      author: Y_Yao
// *      created: 2025-02-18 22:38:43
// **/

// #include<bits/stdc++.h>

// #define int LL
// using namespace std;
// using LL = long long;
// const LL LLINF = 1e18;
// const int INF = 0x3f3f3f3f;
// const int N = 2e5 + 7;
// struct node
// {
//     int u,v,w,id;
// };

// struct node2
// {
//     int count,id;
// };

// node E[N];
// int fa[N],sz[N];
// int n;
// node2 cnt[N];

// bool cmp(node& n1,node& n2)
// {
//     return n1.w < n2.w;
// }

// int find(int x)
// {
//     if(x == fa[x]) return x;
//     else fa[x] = find(fa[x]);
//     return fa[x];
// }

// void Union(int u,int v)
// {
//     u = find(u);
//     v = find(v);
//     if(u == v) return;
//     if(sz[u] > sz[v]) swap(u,v);
//     fa[u] = v;
//     sz[v] += sz[u];
// }

// void solve()
// {
//     cin >> n;
//     for(int i = 1;i <= n - 1;i++)
//     {
//         cin >> E[i].u >> E[i].v >> E[i].w;
//         E[i].id = i;
//     }

//     sort(E + 1,E + n,cmp);

//     for(int i = 1;i <= n;i++)
//     {
//         fa[i] = i;
//         sz[i] = 1;
//     }

//     int mx = 0;
//     for(int i = 1;i <= n - 1;)
//     {
//         //分组
//         vector<int> g;
//         int j = i;
//         while(j < n && E[i].w == E[j].w)
//         {
//             g.push_back(j);
//             j++;
//         }

//         node tmp = E[i];
//         node2 t2;
//         t2.count = sz[find(tmp.u)] * sz[find(tmp.v)] * 2;
//         t2.id = tmp.id;
//         cnt[i] = t2;
//         Union(tmp.u,tmp.v);
//         mx = max(mx,cnt[i].count);
//         i = j;
//     }

//     vector<int> ans;
//     for(int i = 1;i <= n - 1;i++)
//     {
//         if(cnt[i].count == mx)
//         {
//             ans.push_back(cnt[i].id);
//         }
//     }

//     cout << mx << " " << ans.size() << endl;
//     for(auto& e : ans)
//     {
//         cout << e << " ";
//     }
// }

// signed main()
// {
//     ios::sync_with_stdio(false);
//     cin.tie(0);

//     int t = 1;
//     //cin >> t;
//     while(t--)
//     {
//         solve();
//     }
//     return 0;
// }
#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <unordered_set>
using namespace std;

struct Edge {
    int u, v, d, index;
};

struct DSU {
    vector<int> parent, size;
    DSU(int n) {
        parent.resize(n + 1);
        size.resize(n + 1, 1);
        for (int i = 1; i <= n; ++i) parent[i] = i;
    }
    int find(int u) {
        if (parent[u] != u) parent[u] = find(parent[u]);
        return parent[u];
    }
    void unite(int u, int v) {
        u = find(u), v = find(v);
        if (u == v) return;
        if (size[u] < size[v]) swap(u, v);
        parent[v] = u;
        size[u] += size[v];
    }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n;
    cin >> n;
    vector<Edge> edges;
    for (int i = 1; i <= n - 1; ++i) {
        int u, v, d;
        cin >> u >> v >> d;
        edges.push_back({u, v, d, i});
    }
    sort(edges.begin(), edges.end(), [](const Edge& a, const Edge& b) {
        return a.d < b.d;
    });
    DSU dsu(n);
    vector<long long> ans(n + 1, 0); // ans[i] 对应第i条边的贡献
    int i = 0;
    while (i < edges.size()) {
        int current_d = edges[i].d;
        vector<Edge> group;
        while (i < edges.size() && edges[i].d == current_d) {
            group.push_back(edges[i]);
            ++i;
        }
        unordered_map<int, vector<pair<int, int>>> adj;
        unordered_set<int> nodes;
        vector<tuple<int, int, int>> valid_edges;
        for (const auto& e : group) {
            int u = dsu.find(e.u);
            int v = dsu.find(e.v);
            if (u != v) {
                valid_edges.emplace_back(u, v, e.index);
                nodes.insert(u);
                nodes.insert(v);
            }
        }
        for (const auto& [u, v, idx] : valid_edges) {
            adj[u].emplace_back(v, idx);
            adj[v].emplace_back(u, idx);
        }
        unordered_set<int> visited;
        for (int node : nodes) {
            if (visited.count(node)) continue;
            vector<int> component;
            // 计算连通分量
            int sum_total = 0;
            vector<int> stack;
            stack.push_back(node);
            visited.insert(node);
            sum_total += dsu.size[node];
            component.push_back(node);
            while (!stack.empty()) {
                int u = stack.back();
                stack.pop_back();
                for (const auto& [v, idx] : adj[u]) {
                    if (!visited.count(v)) {
                        visited.insert(v);
                        stack.push_back(v);
                        sum_total += dsu.size[v];
                        component.push_back(v);
                    }
                }
            }
            // DFS计算贡献
            unordered_set<int> vis;
            auto dfs = [&](auto&& self, int u) -> int {
                vis.insert(u); 
                int total = dsu.size[u];
                for (const auto& [v, idx] : adj[u]) {
                    if (!vis.count(v)) {
                        int sz = self(self, v);
                        ans[idx] = 1LL * sz * (sum_total - sz) * 2;
                        total += sz;
                    }
                }
                return total;
            };
            dfs(dfs, node);
        }
        // 合并当前组的边
        for (const auto& [u, v, idx] : valid_edges) {
            dsu.unite(u, v);
        }
    }
    // 统计结果
    long long max_val = 0;
    int count = 0;
    vector<int> res;
    for (int i = 1; i <= n; ++i) {
        if (ans[i] > max_val) {
            max_val = ans[i];
            count = 1;
            res = {i};
        } else if (ans[i] == max_val) {
            ++count;
            res.push_back(i);
        }
    }
    sort(res.begin(), res.end());
    cout << max_val << ' ' << count << '\n';
    for (int x : res) cout << x << ' ';
    return 0;
}